﻿
Imports System.Threading
Imports std
Imports storoomc

Public Module _synchelper
    Public Delegate Sub syncImplDelegate(ByVal host As String, ByVal port As Int32, _
                                         ByVal slices As vector(Of storageInterface))

    Private Class syncInfo
        Public impl As syncImplDelegate = Nothing
        Public slices As vector(Of storageInterface) = Nothing
        Public host As String = Nothing
        Public port As Int32 = 0

        Public Sub New(ByVal impl As syncImplDelegate, ByVal slices As vector(Of storageInterface), _
                       ByVal host As String, ByVal port As Int32)
            Me.impl = impl
            Me.slices = slices
            copy(Me.host, host)
            Me.port = port
        End Sub
    End Class

    Private Sub syncImpl(ByVal input As Object)
        Dim info As syncInfo = Nothing
        info = convertor.cast(Of syncInfo)(input, True)
        Try
            info.impl(info.host, info.port, info.slices)
        Catch ex As ThreadAbortException
            raiseError("thread abort.", errorHandle.errorType.warning)
        Catch ex As Exception
            raiseError("caught unexpected exception, ex " + ex.Message + ", callstack " + ex.StackTrace, _
                       errorHandle.errorType.critical)
        End Try
    End Sub

    Public Function issyncing(ByVal thread As Thread) As Boolean
        Return Not thread Is Nothing AndAlso thread.ThreadState = ThreadState.Running
    End Function

    Public Function synchelper(ByVal impl As syncImplDelegate, _
                               ByVal slices As vector(Of storageInterface), _
                               ByVal host As String, ByVal port As Int32, _
                               Optional ByRef thread As Thread = Nothing) As Boolean
        thread = startThread(AddressOf syncImpl, New syncInfo(impl, slices, host, port))
        Return True
    End Function

    Public Function synchelper(ByVal si As storageInterface, ByVal host As String, ByVal port As Int32) As Boolean
        assert(Not si Is Nothing, "storageInterface is nothing.")
        Dim talk As storoomTalk = Nothing
        'let increase the retrytimes, to decrease the fail rate.
        talk = New storoomTalk(host, port, storoomc.common.talkTime.client2room.retrytimes << 3)

        Try
            'cannot lock all data here, this slice may also accept other operations during sync
            Dim s As [set](Of String) = Nothing
            Dim v As vector(Of String) = Nothing
            If si.list(v) AndAlso vector2set(v, s) AndAlso Not s Is Nothing Then
                Dim it As [set](Of String).iterator = Nothing
                it = s.begin()
                While it <> s.end()
                    Dim b As bytes = Nothing
                    If si.read((+it), b) Then
                        If Not talk.modify((+it), b) Then
                            'network issue
                            raiseError("failed to modify data for key " + (+it) + " to dest server " + _
                                       displayHostPort(host, port), errorHandle.errorType.exclamation)
                        End If
                    Else
                        'may accept other operations during sync, so the data may already be deleted.
                        raiseError("failed to read data for key " + (+it) + " during sync, assume deleted already.")
                    End If
                    it += 1
                End While
            End If
            talk.close()
        Catch ex As ThreadAbortException
            raiseError("thread abort.", errorHandle.errorType.warning)
        Catch ex As Exception
            raiseError("caught unexpected exception, ex " + ex.Message + ", callstack " + ex.StackTrace, _
                       errorHandle.errorType.critical)
        End Try

        Return True
    End Function
End Module
